add api wx_balance_withdraw_api

Brightcells 8 gadi atpakaļ
vecāks
revīzija
fa2729a4e1
5 mainītis faili ar 67 papildinājumiem un 6 dzēšanām
  1. 5 0
      api/urls.py
  2. 5 0
      pai2/settings.py
  3. 40 1
      pay/views.py
  4. 5 0
      utils/error/errno_utils.py
  5. 12 5
      utils/error/response_utils.py

+ 5 - 0
api/urls.py

@@ -99,6 +99,11 @@ urlpatterns += [
99 99
     url(r'^wx/notify_url$', pay_views.wx_notify_url_api, name='wx_notify_url_api'),  # 支付异步通知回调地址
100 100
 ]
101 101
 
102
+# 提现相关
103
+urlpatterns += [
104
+    url(r'^wx/balance_withdraw$', pay_views.wx_balance_withdraw_api, name='wx_balance_withdraw_api'),  # 余额提现: 企业付款/现金红包
105
+]
106
+
102 107
 # 分享相关
103 108
 urlpatterns += [
104 109
     url(r'^wx/jsapi_signature$', wechat_views.wx_jsapi_signature_api, name='wx_jsapi_signature_api'),  # jsapi_signature

+ 5 - 0
pai2/settings.py

@@ -261,6 +261,11 @@ WECHAT = {
261 261
         'appsecret': '',
262 262
         'mchID': '',
263 263
         'apiKey': '',
264
+        'mch_cert': '',
265
+        'mch_key': '',
266
+        'redpacket': {
267
+
268
+        }
264 269
     },
265 270
 }
266 271
 

+ 40 - 1
pay/views.py

@@ -13,7 +13,7 @@ from account.models import LensmanIncomeExpensesInfo, LensmanInfo, UserIncomeExp
13 13
 from group.models import GroupPhotoInfo, GroupPhotoOrderInfo
14 14
 from pay.models import OrderInfo
15 15
 from photo.models import PhotosInfo
16
-from utils.error.errno_utils import GroupPhotoStatusCode, OrderStatusCode
16
+from utils.error.errno_utils import GroupPhotoStatusCode, OrderStatusCode, UserStatusCode, WithdrawStatusCode
17 17
 from utils.error.response_utils import response
18 18
 from utils.page_utils import pagination
19 19
 from utils.redis.rkeys import LENSMAN_PHOTO_PRICE
@@ -329,3 +329,42 @@ def wx_notify_url_api(request):
329 329
     order_paid_success(order)
330 330
 
331 331
     return HttpResponse(settings.WXPAY_NOTIFY_SUCCESS)
332
+
333
+
334
+def wx_balance_withdraw_api(request):
335
+    user_id = request.POST.get('user_id', '')
336
+
337
+    # 用户校验
338
+    try:
339
+        user = UserInfo.objects.get(user_id=user_id)
340
+    except UserInfo.DoesNotExist:
341
+        return response(UserStatusCode.USER_NOT_FOUND)
342
+
343
+    # JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里
344
+    trade_type = request.POST.get('trade_type', '')
345
+    # TRANSFER--企业付款、PACKET--现金红包, 余额提现接口withdraw_type的传参可参考这里
346
+    withdraw_type = request.POST.get('withdraw_type', 'TRANSFER')
347
+    amount = int(request.POST.get('amount', 0))
348
+
349
+    if user.balance < amount:
350
+        return response(WithdrawStatusCode.BALANCE_NOT_ENOUGH)
351
+
352
+    # 根据 trade_type 获取 wechat 配置
353
+    wechat = WECHAT.get(trade_type, {})
354
+    # WeChatPay 初始化
355
+    wxpay = WeChatPay(wechat.get('appID'), wechat.get('apiKey'), wechat.get('mchID'), mch_cert=wechat.get('mch_cert'), mch_key=wechat.get('mch_key'))
356
+
357
+    if withdraw_type == 'TRANSFER':
358
+        wxpay.transfer.transfer(user.wx_uid, amount, u'摄影师余额提现,企业付款', check_name='NO_CHECK')
359
+    elif withdraw_type == 'PACKET':
360
+        wxpay.redpack.send(
361
+            user.wx_uid,
362
+            amount,
363
+            send_name=wechat.get('redpacket', {}).get('SEND_NAME'),
364
+            nick_name=wechat.get('redpacket', {}).get('NICK_NAME'),
365
+            act_name=wechat.get('redpacket', {}).get('ACT_NAME'),
366
+            wishing=wechat.get('redpacket', {}).get('WISHING'),
367
+            remark=wechat.get('redpacket', {}).get('REMARK'),
368
+        )
369
+
370
+    return response(200, 'Withdraw Success', u'提现成功', {})

+ 5 - 0
utils/error/errno_utils.py

@@ -75,6 +75,11 @@ class OrderStatusCode(BaseStatusCode):
75 75
     NO_DETAIL_PERMISSION = StatusCodeField(404015, u'No Detail Permission', description=u'没有详情权限')
76 76
 
77 77
 
78
+class WithdrawStatusCode(BaseStatusCode):
79
+    """ 提现相关错误码 4041xx """
80
+    BALANCE_NOT_ENOUGH = StatusCodeField(404100, u'Balance Not Enough', description=u'提现金额不足')
81
+
82
+
78 83
 class MessageStatusCode(BaseStatusCode):
79 84
     """ 消息相关错误码 4090xx """
80 85
     MESSAGE_NOT_FOUND = StatusCodeField(409001, u'Message Not Found', description=u'消息不存在')

+ 12 - 5
utils/error/response_utils.py

@@ -2,11 +2,18 @@
2 2
 
3 3
 from django.http import JsonResponse
4 4
 
5
+from utils.error.errno_utils import StatusCodeField
5 6
 
6
-def response(status_code, data={}):
7
-    return JsonResponse({
7
+
8
+def response_data(status_code, message=None, description=None, data={}):
9
+    return {
8 10
         'status': status_code,
9
-        'message': status_code.message,
10
-        'description': status_code.description,
11
+        'message': message,
12
+        'description': description,
11 13
         'data': data,
12
-    })
14
+    }
15
+
16
+
17
+def response(status_code, message=None, description=None, data={}):
18
+    message, description = (status_code.message, status_code.description) if isinstance(status_code, StatusCodeField) else (message, description)
19
+    return JsonResponse(response_data(status_code, message, description, data))